import java.util.Date;
/**	
 * This class ...
 */

public class Driver implements Comparable<Driver> 
{
   public String name;
   public int number;
   public int hoursThisWeek;
   public int holidays2;
   //for one day
   public boolean available;

   //how many minutes has the driver worked in one day, max allowed = 300;
   int minInOneDay;
   // how many minutes the driver has before a break
   int availableMinutes;

   //max size a driver won't have more than 10 shifts
   int[] startMin;
   int[] endMin;
   int[] service;
   boolean breakTaken;
   String oneWeekTimetable;
   String assignedBus;
   
   public Driver(int driverID, String theName, int theHours)
   { 
	this.number = driverID;
 	this.name = theName;
	this.hoursThisWeek = theHours;
    this.minInOneDay=0;
    startMin = new int[20];
    endMin = new int[20];
	service = new int[20];
    availableMinutes= 300;
	breakTaken = false;
	oneWeekTimetable = new String();
	holidays2=0;
	assignedBus = "";
   }
   
   //assume that driverList will be ordered each time according to availability
   public static void assignNextBestDriver(int start, int end, Driver[] driversList, 
		   int theService,Date theDate, Bus[] busList)
   {
	   
     //if the end is after 24*60min
     if(end<start && start>1340)
        end+=1440;
     for(int i =0;i<driversList.length;i++)
     {
 	boolean found=true; 
	//CONDITION 1 --check if driver is available
	if(!DriverInfo.isAvailable(driversList[i].number,theDate))
	    found= false; 

	//CONDITION 2 --slot is free
    for(int index=0;index<10&&found;index++) {
  	  if(between(driversList[i].startMin[index],driversList[i].endMin[index],start) ||
         between(driversList[i].startMin[index],driversList[i].endMin[index],end)   ||
         (start<=driversList[i].startMin[index] && end>=driversList[i].endMin[index]))
          found=false;
	  
	  //CONDITION 3 -- check limits including breaks--check if the driver won't have more than the 5 h in a shift
 	  if((!driversList[i].breakTaken)&&((driversList[i].minInOneDay+Math.abs(end-start))>300))found=false; 	
 	  if(driversList[i].breakTaken&&((driversList[i].minInOneDay+Math.abs(end-start))>600))found=false;
    }//for			

        if(found)
        {  
	      // update driver to be busy between start and end and update the minutes in the day
          for(int index =0; index<20;index++){
            if(driversList[i].startMin[index]==driversList[i].endMin[index]&&
               driversList[i].startMin[index]==0)
            {
        	driversList[i].startMin[index]=start;
			driversList[i].endMin[index]=end; 
	        driversList[i].service[index]=theService;
        	driversList[i].minInOneDay+=Math.abs(end-start);
        	driversList[i].availableMinutes-=Math.abs(end-start);
			driversList[i].hoursThisWeek+=Math.abs(end-start);

			if(driversList[i].assignedBus.equals("")){
		           Bus.assignBusToDriver(start, end, driversList[i], theService, theDate, busList);
			}
			else{
			         for(int j = 0; j<busList.length; j++){
				         if(driversList[i].assignedBus.equals(busList[j].busNumber) ){
					     for(int index1 =0; index1<30;index1++)
			                 if(busList[j].startMin[index1]==busList[j].endMin[index1]&&
			                    busList[j].startMin[index1]==0)
			                 {
			            	    busList[j].startMin[index1]=start;
			            	    busList[j].endMin[index1]=end;
			            	    busList[j].service[index1]= theService;
			                 }//if
				         }//for
			         }//for 0-busList.length
			}//else
			//check if driver needs break
			int maxEndMin = 0;
      		    if(!driversList[i].breakTaken&&
                    driversList[i].availableMinutes<15&&
                    driversList[i].availableMinutes>=0)
      		    {
		            for(int j=0;j<20;j++){
		        	if(maxEndMin<driversList[i].endMin[j])
		        	       maxEndMin=driversList[i].endMin[j];
		        	{
      		               driversList[i].startMin[index]=maxEndMin+1;
                           driversList[i].endMin[index]=61+maxEndMin;
			               driversList[i].service[index]=-1;
                           driversList[i].availableMinutes=-1; 
                           driversList[i].breakTaken=true;
                	}
                    }
	            }//if

	            return;
	            //return driversList[i];  

            }//end of if 
          }// end of for 0-20
     
        } //if found

     }//for
     System.out.println("_____________________________________________________"+theService +" "
    		 + start + " " + end); 
     return ;
   }
   
   // var x between start and end -> return true
   static boolean between(int start, int end, int x)
   { 
     if(x>=start&&x<=end)return true;
     else return false;
   }

   @SuppressWarnings("deprecation")
   public void updateDriverTimeTable(Date theDate)
   {
       String dailyTable = new String();
       if(service[0]!=0)
       dailyTable="\n"+this.name+ "\ton: "+theDate.toGMTString()+" "+minInOneDay+"\n";
       for(int i=0;i<20;i++){
           if(this.service[i]==-1) 
              dailyTable+=" Break from: "+this.startMin[i] + " to: "+ this.endMin[i]+"\n";
	   else if(this.service[i]!=0) 
              {dailyTable +="[Service: "+ service[i]+"]From: " + this.startMin[i] + " To: " + this.endMin[i];
              dailyTable +=" Bus Number: "+this.assignedBus+ "\n";}
       }
       oneWeekTimetable+=dailyTable;
       //reset all the information for the driver in one day;
       this.startMin = new int[20];
       this.endMin = new int[20];
       this.service = new int[20];
       this.availableMinutes= 300;
       this.minInOneDay=0;
       this.breakTaken=false;
       this.assignedBus = "";
       DriverInfo.setHoursThisWeek(this.number,this.hoursThisWeek/60);


   }//updateDriver

   public int compareTo(Driver x)
   {
 	if(this.availableMinutes<x.availableMinutes)return 1;
	if(this.availableMinutes>x.availableMinutes)return -1;
	return 0;
   }//compareTo
   @Override 
   public boolean equals( Object x )
   {
        if ( this == x ) return true;
        if ( !(x instanceof Driver) ) return false; 
        else return true;
   }//equals

   public static void sortSmallArray(int[] start, int[] end, int[] service)
   {
       for(int i=0;i<20;i++)
         for(int j=i+1;j<20;j++)
           if(start[i]>start[j]&&start[i]!=0&&start[j]!=0){
              int temp=start[i];start[i]=start[j];start[j]=temp; 
              int temp1=end[i];end[i]=end[j];end[j]=temp1;
              int temp2=service[i];service[i]=service[j];service[j]=temp2;
           }//if
   }

}//Driver
